package com.tiamosu.navigation.utils

import android.annotation.SuppressLint
import android.app.Application
import androidx.core.content.FileProvider

/**
 * @author tiamosu
 * @date 2021/5/14.
 */
object FlyUtils {
    private var application: Application? = null

    fun getApp(): Application {
        if (application != null) {
            return application!!
        }
        init(getApplicationByReflect())
        return checkNotNull(application) { "reflect failed." }
    }

    fun init(app: Application?) {
        if (app == null) return
        if (application == null) {
            application = app
            return
        }
        if (application?.equals(app) == true) return
        application = app
    }

    @SuppressLint("PrivateApi")
    private fun getApplicationByReflect(): Application? {
        try {
            val activityThreadClass = Class.forName("android.app.ActivityThread")
            val thread = getActivityThread() ?: return null
            val app = activityThreadClass.getMethod("getApplication").invoke(thread) ?: return null
            return app as Application
        } catch (e: Exception) {
            e.printStackTrace()
        }
        return null
    }

    private fun getActivityThread(): Any? {
        val activityThread = getActivityThreadInActivityThreadStaticField()
        return activityThread ?: getActivityThreadInActivityThreadStaticMethod()
    }

    @SuppressLint("PrivateApi")
    private fun getActivityThreadInActivityThreadStaticField(): Any? {
        return try {
            val activityThreadClass = Class.forName("android.app.ActivityThread")
            val sCurrentActivityThreadField =
                activityThreadClass.getDeclaredField("sCurrentActivityThread")
            sCurrentActivityThreadField.isAccessible = true
            sCurrentActivityThreadField[null]
        } catch (e: Exception) {
            e.printStackTrace()
            null
        }
    }

    @SuppressLint("PrivateApi")
    private fun getActivityThreadInActivityThreadStaticMethod(): Any? {
        return try {
            val activityThreadClass = Class.forName("android.app.ActivityThread")
            activityThreadClass.getMethod("currentActivityThread").invoke(null)
        } catch (e: Exception) {
            e.printStackTrace()
            null
        }
    }
}

class FlyUtilsFileProvider : FileProvider() {
    override fun onCreate(): Boolean {
        FlyUtils.init(context?.applicationContext as? Application)
        return true
    }
}